﻿using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Base.ModuleBase
{
    public static class NumberBox
    {
        const string ValidChars = "-9203.45678e1";
        public static RoutedCommand UpCommand { get; }=new RoutedCommand("UpCommand",typeof(NumberBox));
        public static RoutedCommand DownCommand { get; }=new RoutedCommand("DownCommand",typeof(NumberBox));

        private static ControlTemplate _numberBoxTemplate;

        public static bool GetIsNumberBox(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsNumberBoxProperty);
        }
        public static void SetIsNumberBox(DependencyObject obj, bool value)
        {
            obj.SetValue(IsNumberBoxProperty, value);
        }
        public static readonly DependencyProperty IsNumberBoxProperty =
            DependencyProperty.RegisterAttached("IsNumberBox", typeof(bool), typeof(NumberBox), new PropertyMetadata(false,OnPropertyChanged));


        public static int? GetMax(DependencyObject obj)
        {
            return (int?)obj.GetValue(MaxProperty);
        }

        public static void SetMax(DependencyObject obj, int? value)
        {
            obj.SetValue(MaxProperty, value);
        }
        public static readonly DependencyProperty MaxProperty =
            DependencyProperty.RegisterAttached("Max", typeof(int?), typeof(NumberBox), new PropertyMetadata(null));


        public static int? GetMin(DependencyObject obj)
        {
            return (int?)obj.GetValue(MinProperty);
        }
        public static void SetMin(DependencyObject obj, int? value)
        {
            obj.SetValue(MinProperty, value);
        }

        public static readonly DependencyProperty MinProperty =
            DependencyProperty.RegisterAttached("Min", typeof(int?), typeof(NumberBox), new PropertyMetadata(null));



        public static Visibility GetShowBtn(DependencyObject obj)
        {
            return (Visibility)obj.GetValue(ShowBtnProperty);
        }

        public static void SetShowBtn(DependencyObject obj, Visibility value)
        {
            obj.SetValue(ShowBtnProperty, value);
        }

        public static readonly DependencyProperty ShowBtnProperty =
            DependencyProperty.RegisterAttached("ShowBtn", typeof(Visibility), typeof(NumberBox), new PropertyMetadata(Visibility.Visible,OnPropertyChanged));






        public static bool GetIsInteger(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsIntegerProperty);
        }

        public static void SetIsInteger(DependencyObject obj, bool value)
        {
            obj.SetValue(IsIntegerProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsInteger.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsIntegerProperty =
            DependencyProperty.RegisterAttached("IsInteger", typeof(bool), typeof(NumberBox), new PropertyMetadata(false));




        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var box = d as TextBox;
            if (box == null) return;
            if (e.Property == NumberBox.IsNumberBoxProperty)
            {
                if (_numberBoxTemplate == null)
                {
                    ResourceDictionary rd = new ResourceDictionary();
                    rd.Source = new Uri("pack://application:,,,/Base.ModuleBase;component/Infrastructures/BtnStylesDic.xaml", UriKind.RelativeOrAbsolute);
                    _numberBoxTemplate = rd["_NumberBoxTemplate"] as ControlTemplate;
                }
                box.SetValue(e.Property,e.NewValue);
                if ((bool) e.NewValue)
                {
                    box.SetValue(InputMethod.PreferredImeStateProperty,InputMethodState.Off);
                    box.SetValue(InputMethod.IsInputMethodEnabledProperty,false);
                    TextCompositionManager.AddPreviewTextInputHandler(box, OnPreviewTextInput);
                    box.Template = _numberBoxTemplate;
                    box.CommandBindings.Add(new CommandBinding(UpCommand,OnUpCommand));
                    box.CommandBindings.Add(new CommandBinding(DownCommand,OnDownCommand));
                    box.LostFocus += Box_LostFocus;
                }
                else
                {
                    TextCompositionManager.RemovePreviewTextInputStartHandler(box, OnPreviewTextInput);
                }
            }
        }

        private static void OnDownCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
            var box = sender as TextBox;
            if (box == null) return;
            if (GetIsNumberBox(box))
            {
                double value;
                if (double.TryParse(box.Text, out value))
                {
                    var min = GetMin(box);
                    if (value <= min)
                        return;
                    box.Text = (--value).ToString();
                }
            }
        }

        private static void OnUpCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
            var box = sender as TextBox;
            if (box == null) return;
           
            if (GetIsNumberBox(box))
            {
                double value;
                if (double.TryParse(box.Text, out value))
                {
                    int? max=GetMax(box);
                        if (value >= max)
                            return;
                    box.Text = (++value).ToString();
                }
            }
        }

    
        private static void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            var box = sender as TextBox;
            if (box == null) return;
            if (GetIsNumberBox(box))
            {
                var result = false;
                if (GetIsInteger(box))
                {
                    result = IntegerRegex.IsMatch(box.Text + e.Text);
                }
                else
                {
                    result = FloatRegex.IsMatch(box.Text + e.Text);
                }
                e.Handled = !result;
            }
        }

        private static void Box_LostFocus(object sender, RoutedEventArgs e)
        {
            //失去焦点时检查数据范围
            var box = sender as TextBox;
            if (GetIsNumberBox(box))
            {
                double value;
                if (double.TryParse(box.Text, out value))
                {
                    int? max = GetMax(box);
                    if (value > max)
                    box.Text = max.ToString();
                    else
                    {
                        int? min = GetMin(box);
                        if (value < min)
                            box.Text = min.ToString();
                    }
                }
            }
        }
        private static Regex IntegerRegex=new Regex(@"^-?[0-9]\d*$");
        private static Regex FloatRegex=new Regex(@"^-?[0-9]\d*(.\d+)?([e|E][1-9]\d*)?$");
       
    }
}
